<?php
/**
 * @filesource OpenTaobao.php
 * @author LD
 * @desc Open.淘宝 cURL 简版API
 * @example
 *   $api = new open_tao();
 *   $api->app_key = 10011555;
 *   $api->secret_code = 'AyzztDFcBEPMmaswcKQZTzWMeqTkRoEx';
 *   //$api->session = '4ayKBxqtgzGe4mbL8+nMi6+szOSJ3eYfMlT2/EWK19yM32PjM8Ka9XaJVdJz5YuYD0aZ9meE4wA=';
 *   $api->method = 'taobao.taobaoke.items.get';
 *   $api->fields = 'iid,num_iid,title,nick,price,click_url';
 *   $api->nick = 'kldoo';
 *   $api->keyword = 'one piece';
 *   
 *   $data = $api->get();
 *   //'error_response'
 */
class OpenTaoBao{
	
	const RETURN_FORMAT_JSON = 'json'; //json xml
	const RETURN_FORMAT_XML = 'xml';
	const API_VERSION = '2.0';
	const SIGN_METHOD = 'hmac'; //'md5';

    const DEFAULT_APPKEY = 10011555;
    const DEFAULT_SECRET_CODE = "AyzztDFcBEPMmaswcKQZTzWMeqTkRoEx";
    const DEFAULT_SESSION = "4ayKBxqtgzGe4mbL8+nMi6+szOSJ3eYfMlT2/EWK19yM32PjM8Ka9XaJVdJz5YuYD0aZ9meE4wA=";
    const DEFAULT_MM = 13354759;
    const DEFAULT_UNICK = "kldoo";

	private $_time_out = 1;
	
	private $_params = array(
		'app_key' => null,
		'secret_code' => null,
		'format' => self::RETURN_FORMAT_JSON,
		'v' => self::API_VERSION,
		'timestamp' => null,
        'sign_method' => self::SIGN_METHOD,
        'session' => null,
		'method' => null,
		'fields' => null,	
	);
	
	private $_config = array(
		'container' => null,
		'url' => null,
	);

    //最终的请求链接
    public $_request_uri;

	public function __construct($test=false){
		$this->config($test);	
	}
	
	public function __set($key, $value){
		$this->_params[$key] = $value;
	}
	
	public function __get($key){
		return isset($this->_params[$key]) ? $this->_params[$key] : null;
	}
	
	/**
	 * 设置环境
	 * @param boolean $test
	 */
	public function config($test=false){
		if($test){
 		    $this->_config['container'] = 'http://container.api.tbsandbox.com/container';
 			$this->_config['url'] = 'http://gw.api.tbsandbox.com/router/rest';
 		}else{
 			$this->_config['url'] = 'http://gw.api.taobao.com/router/rest';
 		    $this->_config['container'] = 'http://container.api.taobao.com/container';
 		}
        return $this;
	}

    /**
     * 设置 time out
     *
     * @param int $time
     */
    public function set_time_out($time=1){
        $this->_time_out = $time; 
    }

    /***
     * 获取淘api原数据
     * 
     * @param $format json, xml
     * @param $reCheck boolean
     *   如果json解析为空, 重新使用xml解析一次
     *
     */
    public function get( $format=self::RETURN_FORMAT_JSON, $reCheck=false ){
        $this->_params['format'] = $format;
        $this->_request_uri = $this->request_uri();
        $data = $this->curl( $this->_request_uri );

        if(empty($data))
            return false;

        switch($format){
            case self::RETURN_FORMAT_JSON:
                $data = $this->getJsonData($data);
                $r_format = self::RETURN_FORMAT_XML;
                break;

            case self::RETURN_FORMAT_XML:
                $data = $this->getXmlData($data);
                $r_format = self::RETURN_FORMAT_JSON;
                break;
            default:
                throw new LogicException(__CLASS__.': param format error. ');
        }

        if( empty($data)){
            if(true == $reCheck){
                return $this->get($r_format, false);
            }
            return false;
        }
        return $data;
    }

	/**
	 * 返回结果
	 * @param array $params
	 */
	public function request_uri($params=null){
		$params = is_null($params) ? $this->_params : null;
		$params['timestamp'] = date('Y-m-d H:i:s');
		$appSecret = $params['secret_code'];
		unset($params['secret_code']);
		
		if(empty($params['session'])) unset($params['session']);
		
		//生成签名
		$sign = $this->createSign($appSecret,$params); 
		
		//组织参数
		$strParam = $this->createStrParam($params);
		$strParam .= 'sign='.$sign; 

		$url = $this->_config['url'].'?'.$strParam;
        
        $this->_request_uri = $url;
        
        return $url; 
	}
	
	/**
	 * 抓取页面
	 * @param string $url
	 * @param int $time_out
	 */
	public function curl($url, $time_out=null){
		// create a new cURL resource
		$ch = curl_init();
		
		$time_out = is_null($time_out) ? $this->_time_out : $time_out;
		if( 0<$time_out ){
			curl_setopt($ch, CURLOPT_TIMEOUT, $time_out);
		}
        // set URL and other appropriate options
        curl_setopt($ch, CURLOPT_URL,  $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        
        // grab URL and pass it to the browser
        $html =  curl_exec($ch);
        curl_close($ch);  // close cURL resource, and free up system resources
        return  (strlen($html)>0) ? $html : false;
	}
	
	//签名函数 
	private function createSign ($appSecret, $paramArr) { 
        $sign = '';
        ksort($paramArr); 
        foreach ($paramArr as $key => $val) { 
	       if ($key !='' && $val !='') { 
	           $sign .= $key.$val; 
	       } 
        }
        switch(self::SIGN_METHOD){
            case 'hmac':
                $sign = strtoupper(hash_hmac('md5',$sign,$appSecret)); //hmac方式
                break;
            case 'md5':
                $sign = strtoupper(md5($appSecret.$sign.$appSecret)); //Md5方式
                break;
            default:
	    	    $sign = strtoupper(md5($appSecret.$sign));
        }

        return $sign; 
	}
	
	//组参函数 
	private function createStrParam ($paramArr) { 
	    $strParam = ''; 
	    foreach ($paramArr as $key => $val) { 
	       if ($key != '' && $val !='') { 
	           $strParam .= $key.'='.urlencode($val).'&'; 
	       } 
	    } 
	    return $strParam; 
	}


    public function getJsonData($json){
        $json = str_replace(array("\n","\r"),"",$json);
            //json_decode(  preg_replace('/\r|\n/i', '', $data), true);
        $json = json_decode($json,true);

        return $json;
    }


    //解析xml函数
    public function getXmlData ($strXml) {
        $pos = strpos($strXml, 'xml');
        if ($pos) {
            $xmlCode=simplexml_load_string($strXml,'SimpleXMLElement', LIBXML_NOCDATA);
            $arrayCode[ $xmlCode->getName() ] = $this->get_object_vars_final($xmlCode);
            return $arrayCode ;
        } else {
            return null;
        }
    }

    public function get_object_vars_final($obj){
        if(is_object($obj)){
            $obj=get_object_vars($obj);
        }
        if(is_array($obj)){
            foreach ($obj as $key=>$value){
                $obj[$key]=$this->get_object_vars_final($value);
            }
        }
        return $obj;
    }

}//END class

